<?php
/**
 * 获取真实IP地址
 * 
 * 返回用户的真实IP地址
 */
function getClientIp()
{
	// 首先检查Cloudflare的特定头部
	if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
		return $_SERVER['HTTP_CF_CONNECTING_IP'];
	}

	// 检查X-Forwarded-For头部，它可能包含多个IP（逗号分隔）
	$forwardedIps = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '';

	// 分割逗号分隔的IP列表，最后一个IP通常是客户端的IP
	$clientIps = array_map('trim', explode(',', $forwardedIps));

	// 如果X-Forwarded-For为空或格式不正确，尝试使用REMOTE_ADDR
	if (empty($clientIps) || !is_array($clientIps)) {
		return $_SERVER['REMOTE_ADDR'] ?? '未知IP';
	}

	// 返回最后一个IP，即客户端IP
	return end($clientIps);
}

/**
 * 记录请求日志
 */
function logRequest()
{
	// 获取请求的PHP文件名
	$scriptName = pathinfo($_SERVER['SCRIPT_NAME'], PATHINFO_FILENAME); //返回文件名而不包含路径
	// 日志文件路径
	$logDir = 'logs';
	if (!is_dir($logDir)) {
		mkdir($logDir, 0755, true); // 如果log目录不存在，则创建
	}
	$logFile = $logDir . '/' . $scriptName . '.log';

	$ip = getClientIp(); // 获取真实IP地址
	$datetime = date('d/M/Y:H:i:s O'); // 获取当前日期和时间
	$method = $_SERVER['REQUEST_METHOD']; // 获取请求方法，如GET或POST
	$uri = $_SERVER['REQUEST_URI']; // 获取请求URI
	$protocol = $_SERVER['SERVER_PROTOCOL']; // 获取协议版本，如HTTP/1.1
	$status = http_response_code(); // 获取响应状态码，如200
	$responseSize = ob_get_length(); // 获取响应内容的大小
	$requestSize = $_SERVER['CONTENT_LENGTH'] ?? strlen(file_get_contents('php://input')); // 获取请求内容的大小，如果CONTENT_LENGTH不可用，则计算实际内容的大小
	$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '-'; // 获取Referer头信息
	$userAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '-'; // 获取User-Agent头信息

	// 格式化日志条目，类似于Nginx的日志格式，不包含sessionid
	$logEntry = sprintf(
		'%s - - [%s] "%s %s %s" %d %d %d "%s" "%s"' . PHP_EOL,
		$ip,
		$datetime,
		$method,
		$uri,
		$protocol,
		$status,
		$responseSize,
		$requestSize,
		$referer,
		$userAgent
	);

	// 将日志条目追加到日志文件中
	file_put_contents($logFile, $logEntry, FILE_APPEND);
}
// 开启输出缓冲区以计算响应大小
ob_start();
// 这里是你的实际业务逻辑

// 在脚本结束前记录请求
logRequest();

// 结束输出缓冲区并发送输出
ob_end_flush();

?>